package com.example.blog.service.impl;

import com.example.blog.dto.LikeDTO;
import com.example.blog.entity.Article;
import com.example.blog.entity.Like;
import com.example.blog.entity.User;
import com.example.blog.exception.ResourceNotFoundException;
import com.example.blog.repository.ArticleRepository;
import com.example.blog.repository.LikeRepository;
import com.example.blog.repository.UserRepository;
import com.example.blog.service.LikeService;
import com.example.blog.service.NotificationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class LikeServiceImpl implements LikeService {
    @Autowired
    private LikeRepository likeRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private ArticleRepository articleRepository;

    @Autowired
    private NotificationService notificationService;

    @Override
    @Transactional
    public LikeDTO likeArticle(Long articleId) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new ResourceNotFoundException("User", "username", username));

        Article article = articleRepository.findById(articleId)
                .orElseThrow(() -> new ResourceNotFoundException("Article", "id", articleId));

        if (likeRepository.existsByUserAndArticle(user, article)) {
            throw new RuntimeException("You have already liked this article");
        }

        Like like = new Like();
        like.setUser(user);
        like.setArticle(article);
        Like savedLike = likeRepository.save(like);

        // Create notification for article author
        if (!article.getAuthor().getId().equals(user.getId())) {
            NotificationDTO notification = new NotificationDTO();
            notification.setUserId(article.getAuthor().getId());
            notification.setTitle("New Like");
            notification.setMessage(user.getUsername() + " liked your article: " + article.getTitle());
            notification.setType("LIKE");
            notification.setEntityId(article.getId());
            notification.setEntityType("ARTICLE");
            notificationService.createNotification(notification);
        }

        return convertToDTO(savedLike);
    }

    @Override
    @Transactional
    public void unlikeArticle(Long articleId) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new ResourceNotFoundException("User", "username", username));

        Article article = articleRepository.findById(articleId)
                .orElseThrow(() -> new ResourceNotFoundException("Article", "id", articleId));

        Like like = likeRepository.findByUserAndArticle(user, article)
                .orElseThrow(() -> new ResourceNotFoundException("Like", "article_id", articleId));

        likeRepository.delete(like);
    }

    @Override
    public boolean hasLiked(Long articleId) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new ResourceNotFoundException("User", "username", username));

        Article article = articleRepository.findById(articleId)
                .orElseThrow(() -> new ResourceNotFoundException("Article", "id", articleId));

        return likeRepository.existsByUserAndArticle(user, article);
    }

    @Override
    public Page<LikeDTO> getUserLikes(Long userId, Pageable pageable) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("User", "id", userId));

        return likeRepository.findByUser(user, pageable)
                .map(this::convertToDTO);
    }

    @Override
    public Page<LikeDTO> getArticleLikes(Long articleId, Pageable pageable) {
        Article article = articleRepository.findById(articleId)
                .orElseThrow(() -> new ResourceNotFoundException("Article", "id", articleId));

        return likeRepository.findByArticle(article, pageable)
                .map(this::convertToDTO);
    }

    @Override
    public long getArticleLikesCount(Long articleId) {
        Article article = articleRepository.findById(articleId)
                .orElseThrow(() -> new ResourceNotFoundException("Article", "id", articleId));

        return likeRepository.countByArticle(article);
    }

    private LikeDTO convertToDTO(Like like) {
        LikeDTO dto = new LikeDTO();
        dto.setId(like.getId());
        dto.setUserId(like.getUser().getId());
        dto.setUsername(like.getUser().getUsername());
        dto.setArticleId(like.getArticle().getId());
        dto.setArticleTitle(like.getArticle().getTitle());
        dto.setCreatedAt(like.getCreatedAt());
        return dto;
    }
} 